#ifndef _Resources_H
#define _Resources_H

#include <iostream>

using namespace std;

#include <sys/time.h>
#include <time.h>
#include <sys/resource.h>
#include <unistd.h>

class ResourcesUsageCounter
{
  public:
    /// Reset the resources usage counter 
    void reset(){ 
      userT.tv_sec = systemT.tv_sec = totalT.tv_sec = 0; 
      userT.tv_usec = systemT.tv_usec = totalT.tv_usec = 0; 
      counterStop = true;
    }

    /// Start resource usage counter.
    // Once the counter is started, no start() can change its state
    // unless a stop() occurs. 
    void start();

    /// Stop resource usage counter.
    // Once the counter is stopped, no stop() can change its state
    // unless a start() occurs. 
    void stop();

    /// Constructor.  Start recording resource usage.
    ResourcesUsageCounter() { reset(); }

    /**
     * Return the user time spent on behalf of this process between
     * the last calls to start() and record().
     */
    timeval userTimeInc();

    /**
     * Return the system time spent on behalf of this process between
     * the last calls to start() and record().
     */
    timeval systemTimeInc();
 
    /**
     * Return the sum of the system and user time spent on behalf of
     * this process between the last calls to start() and record().
     */
    timeval totalTimeInc();

    ostream& 
      ResourcesUsageCounter::printTime(ostream& os, const timeval& tv) const; 
    ostream& ResourcesUsageCounter::print(ostream& os) const; 
    // wostream& print(wostream& wos); 

    friend ostream& operator<<(
        ostream& os, const ResourcesUsageCounter& counter)
    {
        return counter.print(os);
    }

    // get the time elpased in seconds
    double getUserT(){ 
      return (double)userT.tv_sec +(double)userT.tv_usec/1000000.0;
    }
    
    double getSystemT(){
      return (double)systemT.tv_sec +(double)systemT.tv_usec/1000000.0;
    }

    double getTotalT(){
      return (double)totalT.tv_sec +(double)totalT.tv_usec/1000000.0;
    }

    /// Add two timeval structures.
    void add(
        const timeval& t1,
        const timeval& t2,
        timeval& result);
                                                                                
    /// Substract two timeval structures.
    void substract(
        const timeval& final,
        const timeval& initial,
        timeval& result);
 
  private:
    /// Copy constructor.  Not supported.
    ResourcesUsageCounter(const ResourcesUsageCounter&);

    /// Assignment operator.  Not supported.
    ResourcesUsageCounter& operator=(const ResourcesUsageCounter&);
                                                                               
    /// Initial resource usage.
    rusage m_initialResourceUsage;

    /// Final resource usage.
    rusage m_finalResourceUsage;

    /// The time when start() got last called.
    timeval m_initialTimeStamp;

    /// The time when stop() got last called.
    timeval m_finalTimeStamp;

    /// The user, system, and total time accumulated after the latest reset().
    /// totalT = userT + systemT
    timeval userT, systemT, totalT;

    /// Indicate the counter is in 'start' state of 'stop' state.
    bool counterStop; 
};
#endif
